{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<class '__main__.A'>, <class 'object'>)\n",
      "(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)\n",
      "(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)\n"
     ]
    }
   ],
   "source": [
    "class A():\n",
    "    pass\n",
    "\n",
    "class B(A):\n",
    "    pass\n",
    "\n",
    "class C(B,A):\n",
    "    pass\n",
    "\n",
    "print(A.__mro__)\n",
    "print(B.__mro__)\n",
    "print(C.__mro__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 单继承和多继承\n",
    "- 单继承：每个类只能继承一个类（每个人只能一个爹）\n",
    "- 多继承：每个类允许继承多个类（会造成挺多麻烦）\n",
    "\n",
    "-优缺点：\n",
    "    - 单继承：\n",
    "        - 传承有序逻辑清晰语法简单隐患少\n",
    "        - 功能不能无限拓展，只能在当前唯一的继承连中扩展\n",
    "    - 多继承：\n",
    "        - 优点：类的功能扩展方便\n",
    "        - 缺点：继承关系混乱"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "flying\n",
      "swimming\n"
     ]
    }
   ],
   "source": [
    "# 多继承例子\n",
    "# 子类可以直接拥有父类的属性和方法，私有属性和方法除外\n",
    "class Fish():\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "    def swim(self):\n",
    "        print('swimming')\n",
    "\n",
    "class Bird():\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "    def fly(self):\n",
    "        print('flying')\n",
    "\n",
    "class Person():\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "    def work(self):\n",
    "        print('working')\n",
    "\n",
    "class SuperMan(Person, Bird, Fish):\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "\n",
    "s = SuperMan('yueyue')\n",
    "s.fly()\n",
    "s.swim()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "working\n"
     ]
    }
   ],
   "source": [
    "# 单继承例子\n",
    "class Student(Person):\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "\n",
    "stu = Student('yueyue')\n",
    "stu.work()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 菱形继承/钻石继承\n",
    "    - 多个子类继承自同一个父类，这些子类由被同一个类继承，于是继承关系图形成一个菱形图谱\n",
    "    - 关于多继承的MRO\n",
    "        - MRO就是多继承中，用于保存继承顺序的一个列表\n",
    "        - Python本身采用C3算法来多多继承的菱形继承进行计算的结果\n",
    "        - MRO列表的计算原则：\n",
    "            - 子类永远在父类前面\n",
    "            - 如果多个父类，则根据继承语法中括号内类的书写顺序存放\n",
    "            - 如果多个类继承了同一个父类，孙子类中只会选取继承语法括号中第一个父类的父类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 菱形继承问题\n",
    "class A():\n",
    "    pass\n",
    "\n",
    "class B(A):\n",
    "    pass\n",
    "\n",
    "class C(A):\n",
    "    pass\n",
    "\n",
    "class D(B,C):\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "From init func\n"
     ]
    }
   ],
   "source": [
    "# 构造函数例子\n",
    "\n",
    "class Person():\n",
    "    # 对Person类进行实例化的时候\n",
    "    # 姓名要确定\n",
    "    # 年龄要确定\n",
    "    # 地址要有\n",
    "    def __init__(self):\n",
    "        self.name = 'NoName'\n",
    "        self.age = 18\n",
    "        self.address = 'StudentHome'\n",
    "        print('From init func')\n",
    "        \n",
    "\n",
    "p = Person()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 构造函数\n",
    "- 在对象进行实例化的时候，系统自动调用的一个函数叫构造函数，通常此函数用来对实例对象进行初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A\n"
     ]
    }
   ],
   "source": [
    "# 构造函数的调用顺序 -1\n",
    "# 如果子类没有写构造函数，则向上自动查找，直到找到为止\n",
    "\n",
    "class A():\n",
    "    def __init__(self):\n",
    "        print('A')\n",
    "\n",
    "class B(A):\n",
    "    pass\n",
    "        \n",
    "class C(B):\n",
    "    pass\n",
    "\n",
    "c = C()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 构造函数的调用顺序 -2\n",
    "class A():\n",
    "    def __init__(self):\n",
    "        print('A')\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self, name):\n",
    "        print('B')\n",
    "        print(name)\n",
    "            \n",
    "class C(B):\n",
    "    pass\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "B\n",
      "我是C\n",
      "这是c的附加功能\n"
     ]
    }
   ],
   "source": [
    "# 构造函数的调用顺序 -3\n",
    "class A():\n",
    "    def __init__(self):\n",
    "        print('A')\n",
    "\n",
    "class B(A):\n",
    "    def __init__(self, name):\n",
    "        print('B')\n",
    "        print(name)\n",
    "            \n",
    "class C(B):\n",
    "    # 在C中想拓展B的构造函数\n",
    "    # 即调用B的构造函数后再添加一些功能\n",
    "    # 有两种方法实现\n",
    "    # 第一种通过父类名调用\n",
    "    '''\n",
    "    def __init__(self,name):\n",
    "        # 首先调用父类的构造函数\n",
    "        B.__init__(self,name)\n",
    "        # 再增加自己的功能\n",
    "        print('这是c的附加功能')\n",
    "    '''\n",
    "    # 第二种用super\n",
    "    def __init__(self,name):\n",
    "        # 首先调用父类的构造函数\n",
    "        super(C,self).__init__(name)\n",
    "        # 其次再增加自己的功能\n",
    "        print('这是c的附加功能')\n",
    "        \n",
    "c = C('我是C')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 多态\n",
    "- 多态就是同一个对象在不同的情况下有不同的状态呈现\n",
    "- 多态不是语法，是一种设计思想\n",
    "- 多态性，一种调用方式，不同的执行效果\n",
    "- 多态：同一事物的多种形态，比如动物分为人类，狗类，猪类\n",
    "\n",
    "# MiXin设计模式\n",
    "- 主要采取多继承的方式对类的功能进行拓展\n",
    "- 是用MiXin实现多继承的时候，要小心\n",
    "    - 首先必须表示单一的功能，而不是某个物品\n",
    "    - 职责必须单一，如果有多个功能，则写多个MiXin\n",
    "    - MiXin不能依赖于子类的实现\n",
    "    - 子类即使没有继承这个MiXin类，也能照常工作，只是缺少了某个功能\n",
    "-优点：\n",
    "    - 使用MiXin可以在不对类进行任何修改的情况下，实现新的功能\n",
    "    - 可以方便的组织维护不同功能组件的划分\n",
    "    - 可以根据需要任意调整功能类的组合\n",
    "    - 可以避免创建很多新的类，导致类的继承混乱"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<class '__main__.Tutor'>, <class '__main__.Teacher'>, <class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)\n",
      "********************\n",
      "(<class '__main__.TutorMiXin'>, <class '__main__.TeacherMiXin'>, <class '__main__.StudentMiXin'>, <class 'object'>)\n"
     ]
    }
   ],
   "source": [
    "# MiXin案例\n",
    "class Person():\n",
    "    name = 'cheng'\n",
    "    age = 28\n",
    "    \n",
    "    def eat(self):\n",
    "        print('eating')\n",
    "    \n",
    "    def drink(self):\n",
    "        print('drinking')\n",
    "        \n",
    "    def sleep(self):\n",
    "        print('sleeping')\n",
    "        \n",
    "class Teacher(Person):\n",
    "    def work(self):\n",
    "        print('working')\n",
    "\n",
    "class Student(Person):\n",
    "    def study(self):\n",
    "        print('studing')\n",
    "        \n",
    "class Tutor(Teacher,Student):\n",
    "    pass\n",
    "\n",
    "t = Tutor()\n",
    "print(Tutor.__mro__)\n",
    "\n",
    "print('*' * 20)\n",
    "\n",
    "class TeacherMiXin():\n",
    "    def work(self):\n",
    "        print('work')\n",
    "class StudentMiXin():\n",
    "    def study(self):\n",
    "        print('study')\n",
    "\n",
    "class TutorMiXin(TeacherMiXin,StudentMiXin):\n",
    "    pass\n",
    "\n",
    "tt = TutorMiXin()\n",
    "print(TutorMiXin.__mro__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类相关函数\n",
    "- issubclass ：检查一个类是否是另一个类的子类\n",
    "- isinstance：检查一个对象是否是一个类的实例\n",
    "- hasattr：检测一个对象是否有成员‘XXX'\n",
    "- getattr\n",
    "- setattr\n",
    "- delattr\n",
    "- dir：获取对象的成员列表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的成员描述符（属性）\n",
    "- 类的成员描述符是为了在类中对类的成员属性进行相关操作而创建的一种方式\n",
    "    - get：获取属性操作\n",
    "    - set：修改或添加属性\n",
    "    - delete： 删除属性操作\n",
    "- 如果想使用类的成员描述符\n",
    "     - 使用类实现描述器\n",
    "     - 使用属性修饰符\n",
    "     - 使用property函数\n",
    "         - property(fget, fset, fdel, doc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hi my name is CHENG\n",
      "Hi my name is FEI\n"
     ]
    }
   ],
   "source": [
    "# 属性案例\n",
    "# 创建Student类，描述学生类\n",
    "# 学生具有Student.name属性\n",
    "# 但name格式并不统一\n",
    "\n",
    "class Student():\n",
    "    def __init__(self,name,age):\n",
    "        self.name = name\n",
    "        self.age = age\n",
    "        \n",
    "        self.setName(name)\n",
    "    # 介绍下自己\n",
    "    def intro(self):\n",
    "        print('Hi my name is {0}'.format(self.name))\n",
    "        \n",
    "    def setName(self,name):\n",
    "        self.name = name.upper()\n",
    "        \n",
    "        \n",
    "s1 = Student('cheng',28)\n",
    "s2 = Student('fei',27)\n",
    "s1.intro()\n",
    "s2.intro()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# property 案例\n",
    "\n",
    "class Person():\n",
    "    def fget(self):\n",
    "        return self._name * 2\n",
    "    \n",
    "    def fset(self,name):\n",
    "        self._name =  name.upper()\n",
    "        \n",
    "    def fdel(self):\n",
    "        self._name = 'NoName'\n",
    "        \n",
    "    name = property(fget, fset, fdel, '对name进行操作了')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "TULINGTULING\n"
     ]
    }
   ],
   "source": [
    "p1 = Person()\n",
    "p1.name = 'tuling'\n",
    "print(p1.name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类的常用魔术方法\n",
    "- 魔术方法就是不需要认为调用的方法，基本是在特定时刻自动触发\n",
    "- 魔术方法有个统一特征，方法名被前后各两个下划线包裹\n",
    "- __init__：构造函数\n",
    "- __new__:对象实例化方法，此函数较特殊，一般不建议使用\n",
    "- __call__：对象当成函数来使用的时候触发，\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "beidiaoyong\n",
      "too\n"
     ]
    }
   ],
   "source": [
    "# call举例\n",
    "class A():\n",
    "    def __init__(self,name=0):\n",
    "        print('beidiaoyong')\n",
    "        \n",
    "    def __call__(self):\n",
    "        print('too')\n",
    "        \n",
    "a = A()\n",
    "a()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 类和对象的三种方法\n",
    "- 实例方法：\n",
    "    - 需要实例化对象才能使用的方法，使用过程中需要借助对象的其他对象方法使用\n",
    "- 静态方法：\n",
    "    - 不需要实例化，通过类直接访问\n",
    "- 类方法：\n",
    "    - 不需要实例化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<__main__.Person object at 0x102f97a58>\n",
      "eating\n",
      "<class '__main__.Person'>\n",
      "playing\n",
      "<class '__main__.Person'>\n",
      "playing\n",
      "saying\n",
      "saying\n"
     ]
    }
   ],
   "source": [
    "# 三种方法的案例\n",
    "class Person():\n",
    "    # 实例方法\n",
    "    def eat(self):\n",
    "        print(self)\n",
    "        print('eating')\n",
    "      \n",
    "    # 类方法\n",
    "    @classmethod\n",
    "    def play(cls):\n",
    "        print(cls)\n",
    "        print('playing')\n",
    "        \n",
    "    # 静态方法,不需要第一个参数\n",
    "    @staticmethod\n",
    "    def say():\n",
    "        print('saying')\n",
    "        \n",
    "yueyue = Person()\n",
    "# 实例方法\n",
    "yueyue.eat()\n",
    "# 类方法\n",
    "Person.play()\n",
    "yueyue.play()\n",
    "# 静态方法\n",
    "Person.say()\n",
    "yueyue.say()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
